<template>
  <div>
    <div class="pageBox">
      <div v-if="isRightDivShow != 'chatList'" class="pageLeft" :class="[isLeftBox ? 'left_width1' : 'left_width2']">
        <div class="historyDiv">
          <div class="history_list_box" v-loading="leftLoading">
            <!-- 历史列表 -->
            <div
              class="history_item_box"
              :class="[chatListId == v.id ? 'history_item_box_active' : '']"
              v-for="v in historyList"
              :key="v.id"
              @click="clickSession(v)"
            >
              <div v-if="!v.isTitle" class="item_title">
                <span class="item_title_cot"></span>
                {{ v.title }}
              </div>
              <div class="history_delete_btn">
                <span>{{ v.createTime }}</span>
                <i class="iconfont-el icon-delete del_icon" @click.stop="deleteTitleClick(v)"></i>
              </div>
            </div>
          </div>
          <div class="history_page">
            <el-pagination
              layout="prev, pager, next"
              :hide-on-single-page="requestHistory.pageCount == 0"
              :pager-count="5"
              :total="requestHistory.total"
              v-model:current-page="requestHistory.pageNum"
              v-model:page-size="requestHistory.pageSize"
              @current-change="handleCurrentChange"
            />
          </div>
        </div>
        <div class="unfold_btn">
          <!-- <div class="btn1 " @click="newCreateChatClick(1)">
            <img src="../../assets/images/chatgpt/agent.png" class="img1" alt="" />
            <span>{{ $t('chatGpt.context') }}</span>
          </div>
          <div class="btn1">
            <img src="../../assets/images/chatgpt/add1.png" class="img2" alt="" />
            <span>创建智能体</span>
          </div> -->
          <div class="new_btn" v-if="!(chatList.length == 0 && !isContextShow)">
            <el-button color="#f08f00" style="color: #fff; width: 247px" @click="newCreateChatClick(4)">新建对话</el-button>
          </div>
        </div>
      </div>
      <div :class="[isLeftBox ? 'pageRight1' : 'pageRight']">
        <div v-if="isRightDivShow != 'chatList'" class="packUpBtn" @click="isLeftBox = !isLeftBox" :title="isLeftBox ? '展开' : '收起'">
          <img v-if="isLeftBox" src="../../assets/images/chatgpt/packup.png" style="width: 8px; transform: rotate(180deg)" alt="" />
          <img v-else src="../../assets/images/chatgpt/packup.png" style="width: 8px" alt="" />
        </div>
        <div class="page_body">
          <!-- 标题 -->
          <div v-if="chatList.length == 0 && !isContextShow" class="body_header">
            <div class="header_left_title">
              <span>有问必答,我是你的</span>
              <span class="left_title_text">智能助手</span>
            </div>
            <div class="header_big_title">
              <img src="../../assets/images/chatgpt/bg2.png" class="img_box" alt="" />
              <div class="big_title_text">
                <span>AI知识问答</span>
                <!-- <span>CPECC-SW AI精灵</span>
                <span class="right_text">西南院AI知识大脑</span> -->
              </div>
            </div>
          </div>
          <!-- 聊天列表 -->
          <div v-else class="chit_chat">
            <div class="chat_list" id="chat-content" ref="chatContent">
              <!-- 语境中心单独显示 -->
              <div v-if="isRightDivShow == 'isContextList'" class="list_item">
                <div class="ai_logo">
                  <svg-icon icon-class="ai_chat2"></svg-icon>
                </div>
                <div class="right_text ai_right_text right_text_header">
                  <div class="ai_text1">{{ $t('chatGpt.chatTitle1') }}{{ ContextMessage.titleName }}</div>
                  <div class="ai_text2">
                    {{ ContextMessage.desc }}
                  </div>
                </div>
              </div>
              <!-- 知识库单独显示 -->
              <div v-if="isRightDivShow == 'isKnowledgeList'" class="list_item">
                <div class="ai_logo">
                  <svg-icon icon-class="ai_chat2"></svg-icon>
                </div>
                <div class="right_text ai_right_text right_text_header">
                  <div class="ai_text1">
                    您已进入知识库中心,当前选择的知识库为:
                    <span style="font-weight: bold">{{ knowledgeMessage?.appName }}</span>
                  </div>
                  <div class="ai_text2">
                    <!-- {{ ContextMessage.desc }} -->
                  </div>
                </div>
              </div>
              <div v-for="(item, index) in chatList" :key="item.id">
                <!-- 自己 -->
                <div v-if="item.name == 'chat_username'" class="list_item list_item_user">
                  <div class="right_text user_right_text">
                    <!-- {{ item.msg }} -->
                    <pre>{{ item.msg }}</pre>
                    <!-- <el-input v-model="item.msg" readonly autosize type="textarea" resize="none"
                      class="input_textarea_msg"></el-input> -->
                  </div>
                  <div class="chat_logoIcon">
                    <img :src="userStore.avatar" class="user-avatar" />
                  </div>
                </div>
                <!-- ai -->
                <div v-else class="list_item">
                  <div class="ai_logo">
                    <!-- <img src="../../../../assets/images/chatgpt/ai1.png" /> -->
                    <svg-icon icon-class="ai_chat2" class="svgIconLogo"></svg-icon>
                  </div>
                  <div class="right_text_box">
                    <div class="name">
                      <!-- <img v-if="item.headImg" :src="$yuUtils.imgSrc(item.headImg)" style="width:20px" /> -->
                      <svg-icon icon-class="a-ziyuan64" class="icon_size1"></svg-icon>
                      <span>{{ item.name }}</span>
                    </div>
                    <div class="right_text ai_right_text">
                      <!-- <div v-html="marked(item.msg.trim())" v-highlight></div> -->
                      <!-- <MdEditor v-model="item.msg" /> -->
                      <MdPreview :id="item?.id" :modelValue="item.msg" :previewTheme="MdEditorV3State.theme" :codeTheme="MdEditorV3State.codeTheme" />
                      <MdCatalog :editorId="item?.id" :scrollElement="scrollElement" />
                      <!--  -->
                      <div v-show="msgLoading && index == chatList.length - 1" class="stop_box">
                        <!-- <el-icon class="is-loading is-loading1" style="color: #e67e22;">
                          <Loading />
                        </el-icon> -->
                        <icon-loading style="color: #e67e22" />
                        <el-tag type="danger" class="stop_icon" @click="stopTextClick">
                          <svg-icon icon-class="stop"></svg-icon>
                          停止回答
                        </el-tag>
                      </div>

                      <!-- dify引用 -->
                      <div v-if="item.retriever_resources && item.retriever_resources.length != 0" class="dify_box">
                        <el-divider content-position="left">
                          <i class="iconfont-el icon-s-flag" style="color: #e67e22"></i>
                          <span style="color: #667085">{{ $t('chatGpt.quote') }}</span>
                        </el-divider>
                        <div class="quote_list">
                          <el-tag
                            v-for="(item1, index) in item.deWeight_retriever_resources"
                            :key="index"
                            type="info"
                            effect="plain"
                            class="falstelTag"
                            @click="openDifyQuoteClick(item.retriever_resources)"
                          >
                            <!-- <i class="iconfont-el icon-tickets"></i> -->
                            <svg-icon :icon-class="selectSvgIcons(item1.document_name)"></svg-icon>
                            {{ item1.document_name }}
                          </el-tag>
                        </div>
                      </div>
                      <!-- fastGPT引用 -->
                      <div v-if="item.flowResponses">
                        <div>
                          <el-divider content-position="left">
                            <i class="iconfont-el icon-s-flag" style="color: #e67e22"></i>
                            <span style="color: #667085">{{ $t('chatGpt.quote') }}</span>
                          </el-divider>
                          <!-- <div>{{item.flowResponses}}</div> -->
                        </div>
                        <div>
                          <el-tag
                            v-for="(item1, index) in showFastQuoteDocClick(item.flowResponses)"
                            :key="index"
                            type="info"
                            effect="plain"
                            class="falstelTag"
                            @click="openFastGptQuoteClick(item.flowResponses)"
                          >
                            <i class="iconfont-el icon-tickets"></i>
                            {{ item1 }}
                          </el-tag>
                        </div>
                        <div class="FastQuote">
                          <!-- 引用总条数 -->
                          <!-- <el-tag v-if="textJsonParseFunc(item.flowResponses).quoteList.length != 0" type=""
                            effect="plain" class="falstelTag" @click="openFastGptQuoteClick(item.flowResponses)">
                            {{ textJsonParseFunc(item.flowResponses).quoteList.length }}{{ $t("chatGpt.quoteCount") }}
                          </el-tag> -->
                        </div>
                      </div>
                    </div>
                    <!-- 重新回答和复制 v-if="!msgLoading && index == chatList.length - 1"-->
                    <div v-if="!msgLoading" class="list_foot" :class="item.isAudio != 'play' ? 'last_foot_visible' : ''" ref="listFootRef">
                      <div v-if="item.isAudio == 'play'" class="div_icon div_icon_volume" title="播放音频" @click="playAudioClick(item)">
                        <svg-icon icon-class="volume"></svg-icon>
                      </div>
                      <div v-else class="div_icon div_icon_volume" title="暂停音频" @click="pauseAudioClick(item)">
                        <svg-icon icon-class="pause" style="color: #f08f00"></svg-icon>
                      </div>
                      <div class="div_icon" title="重新回答" @click="reanswerClick(item, index)">
                        <el-icon>
                          <Refresh />
                        </el-icon>
                      </div>
                      <div class="div_icon" title="复制" @click="copyClick(item.msg)">
                        <el-icon>
                          <CopyDocument />
                        </el-icon>
                      </div>
                    </div>
                    <!-- <div v-if="index != chatList.length - 1" class="list_foot">
                      <div></div>
                      <div class="div_icon" @click="copyClick(item.msg)">
                        <el-icon>
                          <CopyDocument />
                        </el-icon>
                      </div>
                    </div> -->
                  </div>
                </div>
              </div>
            </div>
          </div>
          <!-- 输入框 -->
          <div class="page_input">
            <div class="input_box">
              <el-input
                ref="textInputRefs"
                v-model="inputMsg"
                :autosize="{ minRows: 3 }"
                type="textarea"
                resize="none"
                placeholder="请输入内容"
                @keyup.ctrl.enter.native="handleKeyPress"
                @keydown.enter.exact.native="enterSubmit"
              ></el-input>
              <div class="btn_box">
                <div class="voice_box" title="点击语音输入">
                  <img v-if="isSpeakType == 1" src="../../assets/images/chatgpt/mic.png" style="width: 14px" alt="" @click="startRecordAudio" />
                  <div v-else-if="isSpeakType == 2">
                    <div class="loaderRectangle" @click="stopRecordAudio">
                      <div></div>
                      <div></div>
                      <div></div>
                      <div></div>
                      <div></div>
                    </div>
                  </div>
                  <div v-else-if="isSpeakType == 3" class="SpeakType3">
                    <!-- <el-icon class="is-loading">
                      <Loading />
                    </el-icon> -->
                    <icon-loading style="color: #e67e22" />
                    <span>转码中...</span>
                  </div>
                </div>
                <el-divider direction="vertical" />
                <!-- 发送按钮 -->
                <div class="sendBtn" title="发送" @click="sendText">
                  <svg-icon icon-class="send1"></svg-icon>
                </div>
              </div>
            </div>
            <!-- 新建对话 -->
            <div v-if="!(chatList.length == 0 && !isContextShow)" class="create_btn" title="返回新建对话" @click="newCreateChatClick(2)">
              <CreateBtn></CreateBtn>
            </div>
          </div>
          <!-- dify知识库应用分类 -->
          <div v-if="chatList.length == 0 && !isContextShow">
            <ClassifyList @startChatClick="startChatClick_classifyList"></ClassifyList>
          </div>
        </div>
      </div>
    </div>
    <!-- dify引用详情对话框 -->
    <dify-quote ref="DifyQuoteRefs"></dify-quote>
  </div>
</template>

<script lang="ts" setup>
import { marked } from 'marked';
import { MdPreview, MdCatalog } from 'md-editor-v3';
// preview.css相比style.css少了编辑器那部分样式
import 'md-editor-v3/lib/preview.css';
const scrollElement = document.documentElement;

//@ts-ignore
import Recorder from 'js-audio-recorder';
import axios from 'axios';

import ClassifyList from './components/classifyList.vue';
import CreateBtn from './components/createBtn.vue';
import DifyQuote from './components/dify-quote.vue';

import {
  aiqaWikiRecordList,
  aiqaSensitiveCheckSensitive,
  aiqaWikiRecordCreate,
  aiqaWikiRecordUpdate,
  aiqaWikiRecordDelete,
  aiqaWikiAppsCrCount,
  aiqaWikiAppsGetAuthorizedByDataSetId
} from '@/api/expert/expertApi';

import useUserStore from '@/store/modules/user';
import { getToken } from '@/utils/auth';

const userStore = useUserStore();
const { proxy } = getCurrentInstance() as any;
const route = useRoute();

const isLeftBox = ref(true);
const chatListId = ref(''); //聊天记录的id
const historyList: any = ref([]);
const requestHistory: any = ref({
  pageNum: 1,
  pageSize: 20,
  total: 0,
  pageCount: 0
}); // 历史列表的分页
const leftLoading = ref(false);
// const isShowInput = ref(false);

const inputMsg = ref(''); //输入框的值
const textInputRefs = ref();
/**语音输入 */
const isSpeakType = ref(1); //1:静默状态,还未点击开始录音,2:开始录音,3:结束录音,正在转换中
const recorder: any = new Recorder({
  sampleBits: 16, // 采样位数，支持 8 或 16，默认是16
  sampleRate: 16000, // 采样率，支持 11025、16000、22050、24000、44100、48000，根据浏览器默认值，我的chrome是48000
  numChannels: 1 // 声道，支持 1 或 2， 默认是1
  // compiling: false,(0.x版本中生效,1.x增加中)  // 是否边录边转换，默认是false
});
const isContextShow = ref(false); //语境中心消息显示
const isRightDivShow = ref('chatList'); //chatList:聊天列表,isContextList:语境中心列表,isCollWordList:提示词列表,isKnowledgeList:知识库列表

const chatList = ref([]); //聊天列表
const chatContent = ref();
const chatModelType = ref(1); //模型的type
const ApiKey = ref('');
const ModelListRow: any = ref({
  modelName: 'cpecc 精灵',
  iconUrl: '',
  appKey: '',
  id: '',
  reCount: ''
});
const msgLoading = ref(false);
const modelClassify = ref(2);
/**语境中心--start */
const contextList = ref([]); //语境中心列表
const ContextMessage: any = ref({
  titleName: '',
  desc: ''
});
const assistantId = ref(''); //语境中心id
/**语境中心--end */

/**知识库----start */
const knowledgeMessage: any = ref({});
const dify_conversationId = ref('');
const DifyQuoteRefs = ref();
/**知识库----end */

const inputPlaceholder = ref(proxy.$t('chatGpt.inputPlaceholder'));
const placeholderTemp = ref(proxy.$t('chatGpt.inputPlaceholder'));

/**停止接口请求,停止回答 */
const controller = ref(new AbortController());
// const { signal } = controller.value;

/**Markdown编辑器 */
const MdEditorV3State = reactive({
  theme: 'github',
  codeTheme: 'github'
});
//---------------------------------------------------------------

watch(
  () => isRightDivShow.value,
  (newVal, oldVal) => {
    if (newVal) {
      // isLeftBox
      newVal == 'chatList' ? (isLeftBox.value = true) : (isLeftBox.value = false);
    }
  },
  { deep: true, immediate: true }
);

//查询会话历史列表
const apiChatReGet = () => {
  leftLoading.value = true;
  aiqaWikiRecordList({
    userId: userStore.userId,
    pageNum: requestHistory.value.pageNum,
    pageSize: requestHistory.value.pageSize,
    isAsc: 'desc',
    appId: ModelListRow.value.id,
    expert: 'true'
  })
    .then((res: any) => {
      leftLoading.value = false;
      res.rows.forEach((item) => {
        item.isTitle = false;
      });
      historyList.value = res.rows;
      requestHistory.value.total = res.total;
      requestHistory.value.pageCount = res.pageSize;
    })
    .catch((err) => {
      leftLoading.value = false;
    });
};
//分页change
const handleCurrentChange = (val) => {
  requestHistory.value.pageNum = val;
  apiChatReGet();
};
//点击了历史列表
const clickSession = (v) => {
  // console.log(v);
  clearDataFunc(); //清空
  let chatListData = JSON.parse(v.record);
  chatListData.forEach((item) => {
    item.isAudio = 'play';
  });
  chatList.value = chatListData;
  chatListId.value = v.id;
  isContextShow.value = false;
  if (v.appId) {
    //点击了知识库的问答记录
    isRightDivShow.value = 'isKnowledgeList';
    ModelListRow.value.appKey = v.appKey;
    ApiKey.value = v.appKey;
    ModelListRow.value.modelName = v.appName;
    ModelListRow.value.id = v.appId;
    dify_conversationId.value = v.conversationId;
  } else {
    isRightDivShow.value = 'chatList';
  }
  apiChatReGet();
};

//删除历史记录
const deleteTitleClick = (item: any) => {
  aiqaWikiRecordDelete([item.id]).then((res: any) => {
    if ((chatListId.value = item.id)) {
      newCreateChatClick(2);
    }
    apiChatReGet();
  });
};
// 点击了知识库的开始对话
const startChatClick_classifyList = (val: any) => {
  // console.log(val);
  clearDataFunc(); //清空
  knowledgeMessage.value = val;
  ApiKey.value = val.appKey;
  ModelListRow.value.appKey = val.appKey;
  ModelListRow.value.modelName = val.appName;
  ModelListRow.value.iconUrl = '';
  ModelListRow.value.id = val.id;
  newCreateChatClick(3);
  //去请求这个知识库的问答记录
  requestHistory.value.pageNum = 1;
  apiChatReGet();
};
// 新建对话
const newCreateChatClick = (val: any) => {
  if (val == 1) {
    //语境中心(智能体)
    isRightDivShow.value = 'isContextList';
  }
  if (val == 2) {
    //创建对话
    isRightDivShow.value = 'chatList';
    isContextShow.value = false;
    clearDataFunc();
    apiChatReGet();
  }
  if (val == 3) {
    //知识库
    isRightDivShow.value = 'isKnowledgeList';
    isContextShow.value = true;
  }
  if (val == 4) {
    // 知识库应用不变,只是清空聊天记录,重新使用模型穿件对话
    isRightDivShow.value = 'isKnowledgeList';
    isContextShow.value = true;
    chatList.value = [];
    chatListId.value = '';
    dify_conversationId.value = '';
  }
};
// 清空对话框数据
const clearDataFunc = () => {
  chatList.value = [];
  chatListId.value = '';
  assistantId.value = '';
  Object.keys(ContextMessage.value).forEach((key) => (ContextMessage.value[key] = '')); //清空语境中心数据
  Object.keys(ModelListRow.value).forEach((key) => (ModelListRow.value[key] = '')); //清空选中模型数据
  knowledgeMessage.value = {}; //清空知识库数据
  inputPlaceholder.value = placeholderTemp.value;
  ApiKey.value = '';
  dify_conversationId.value = '';
  requestHistory.value.pageNum = 1;
};

// 重新回答
const reanswerClick = (item, index) => {
  inputMsg.value = chatList.value[index - 1].msg;
  sendText();
};

// 停止回答
const stopTextClick = () => {
  controller.value.abort();
  controller.value = new AbortController();
};
// 发送消息
const sendText = () => {
  //判断api-key是否存在
  // if (!this.$store.state.settings.openAiToken) {
  //   this.$notify({
  //     title: this.$t("commen.title"),
  //     type: "warning",
  //     message: this.$t("chatGpt.opanToken"),
  //     duration: 0
  //   });
  //   return;
  // }
  if (msgLoading.value) {
    proxy?.$modal.msgWarning('正在回答中,无法发起新的问答!');
    return;
  }
  if (!ApiKey.value) {
    proxy?.$modal.msgWarning('请选择一个知识库');
    return;
  }
  let chatMsgObj = {
    headImg: '',
    name: 'chat_username',
    time: proxy?.$moment().format('YYYY-MM-DD hh:mm:ss'),
    msg: inputMsg.value,
    chatType: 0, //信息类型，0文字，1图片
    uid: 'jcm' //uid
  };
  //如果消息不为空
  if (inputMsg.value.trim() === '') {
    proxy?.$modal.msgWarning(proxy.$t('chatGpt.chatMsg1'));
  } else {
    apiChatReCheckSensitive(chatMsgObj);
  }
};
// 判断敏感字
const apiChatReCheckSensitive = (chatMsgObj: any) => {
  aiqaSensitiveCheckSensitive({ string: chatMsgObj.msg }).then((res: any) => {
    if (res.code === '500') {
      proxy?.$modal.msgError(`${res.obj}`);
      return;
    }
    chatList.value.push(chatMsgObj);
    inputMsg.value = '';
    chatCompletion();
    WikiAppsCrCount(); //记录次数
  });
};
// 流式数据会有被截断的情况，需要做一些容错处理
const chunkRef = ref();
const handleChunkData = (chunk: string) => {
  chunk = chunk.trim();
  // 如果存在上一个切片
  if (chunkRef.value) {
    chunk = chunkRef.value + chunk;
    chunkRef.value = '';
  }

  // 如果存在done,认为是完整切片且是最后一个切片
  if (chunk.includes('[DONE]')) {
    return chunk;
  }

  // 最后一个字符串不为}，则默认切片不完整，保存与下次拼接使用（这种方法不严谨，但已经能解决大部分场景的问题）
  if (chunk[chunk.length - 1] !== '}') {
    chunkRef.value = chunk;
  }
  return chunk;
};
//发送消息接口
const chatCompletion = async () => {
  let messages = [];
  let historyMessage = chatList.value.map((item) => {
    if (item.uid == 'assistant') {
      return {
        role: 'assistant',
        content: item.msg
      };
    } else {
      return {
        role: 'user',
        content: item.msg
      };
    }
  });
  // 如果选择的 附带历史消息数 大于全部历史消息数
  //  if (historyMessage.length > this.messageValue) {
  //       let end = historyMessage.length - this.messageValue - 1;
  //       // 截取需要发送请求的消息列表
  //       historyMessage.splice(0, end);
  //     }

  // 如果语境中心,需要加一条消息
  // if (isContextShow.value) {
  //   let mesg = [
  //     {
  //       role: "user",
  //       content: ContextMessage.value.command
  //     }
  //   ];
  //   messages = [...mesg, ...historyMessage];
  // } else {
  messages = historyMessage;
  // }
  // 新增一个机器人的空消息
  let chatBeforResMsg = {
    headImg: ModelListRow.value.iconUrl,
    name: ModelListRow.value.modelName,
    time: proxy.$moment().format('YYYY-MM-DD hh:mm:ss'),
    msg: '',
    isAudio: 'play',
    chatType: 0, //信息类型，0文字，1图片
    uid: 'assistant' //uid
  };
  sendMsg(chatBeforResMsg);
  let currentResLocation = chatList.value.length - 1;
  let headers = {
    Authorization: getToken(),
    'Content-Type': 'application/json',
    Accept: 'text/event-stream',
    Connection: 'keep-alive',
    'api-key': ApiKey.value
    // "api-type": chatModelType.value
  };
  msgLoading.value = true;
  // 知识库应用模型
  if (modelClassify.value == 2) {
    let objParams = {
      // messages: messages,
      query: messages[messages.length - 1].content,
      apiKey: ApiKey.value,
      conversationId: dify_conversationId.value
    };
    chatList.value[currentResLocation].retriever_resources = [];

    await fetch(`${import.meta.env.VITE_APP_BASE_API}/aiqa/dify/chat-messages`, {
      method: 'POST',
      timeout: 120000,
      signal: controller.value.signal, //停止请求
      headers: {
        Authorization: 'Bearer ' + getToken(), //唐云龙接口使用,直连请注释
        'Content-Type': 'application/json',
        clientid: import.meta.env.VITE_APP_CLIENT_ID
      },
      body: JSON.stringify(objParams)
    } as any)
      .then((response: any) => {
        return response;
      })
      .then(async (response: any) => {
        const reader = response.body.getReader(); // 创建读取器
        const decoder = new TextDecoder(); // 创建解码器
        while (1) {
          // 循环读取内容
          /* 读取其中一部分内容 done 是否读取完成， value 读取到的内容 */
          const { done, value } = await reader.read();
          if (done) {
            msgLoading.value = false;
            return;
          }
          const text = decoder.decode(value); // 利用解码器把数据解析成字符串
          const chunk = handleChunkData(text); // 处理切片数据
          // 判断是否有不完整切片，如果有，合并下一次处理，没有则获取数据
          if (chunkRef.value) continue;
          // console.log(chunk, 'chunk');
          // 解析数据
          let decodedArray = chunk.split('data:');
          if (decodedArray.length == 1 && decodedArray[0] != '') {
            // 错误信息处理
            let errObj = JSON.parse(decodedArray[0]);
            if (errObj.code == 500) {
              msgLoading.value = false;
              proxy?.$modal.msgError(errObj.msg);
            }
          }
          // 获取可用数据
          if (decodedArray[1]) {
            console.log(JSON.parse(decodedArray[1]));
            let difyData = JSON.parse(decodedArray[1]);
            if (difyData.event == 'message') {
              dify_conversationId.value = difyData.conversation_id;
              const response = difyData.answer ? difyData.answer : '';
              chatList.value[currentResLocation].msg = chatList.value[currentResLocation].msg + response;
              scrollBottom();
            } else if (difyData.event == 'message_end') {
              msgLoading.value = false;
              if (difyData.metadata.retriever_resources) {
                // 引用
                chatList.value[currentResLocation].retriever_resources = difyData.metadata.retriever_resources;
                //引用去重
                chatList.value[currentResLocation].deWeight_retriever_resources = chatList.value[currentResLocation].retriever_resources.filter(
                  (item, index, self) => {
                    return self.findIndex((t) => t.document_name === item.document_name) === index;
                  }
                );
              }

              // 更新会话
              moreRequestData(messages);
              scrollBottom();
            }
          }
        }
      })
      .catch((error) => {
        msgLoading.value = false;
        moreRequestData(messages);
      });
  } else {
  }
};

// 数量统计接口
const WikiAppsCrCount = () => {
  aiqaWikiAppsCrCount(ModelListRow.value.id);
};

// 整合机器人返回结束其他请求的处理
const moreRequestData = (messages: any) => {
  // 处理创建会话和知乎部分
  let createParams = {};
  let updateParams = {};
  // console.log(messages);
  if (isRightDivShow.value == 'isContextList') {
    // 语境中心
    if (messages.length == 2) {
      createParams = {
        title: messages[0].content,
        record: chatList.value,
        reCount: chatList.value.length,
        assistantId: assistantId.value,
        userId: userStore.userId
      };

      apiChatReCreate(createParams);
    }
    if (messages.length > 2) {
      updateParams = {
        id: chatListId.value,
        record: chatList.value,
        reCount: chatList.value.length,
        assistantId: assistantId.value
      };

      apiChatReModify(updateParams);
    }
  } else {
    //普通问答
    if (messages.length == 1) {
      // 创建会话
      createParams = {
        title: messages[0].content,
        record: JSON.stringify(chatList.value),
        reCount: chatList.value.length,
        userId: userStore.userId,
        appId: ModelListRow.value.id,
        conversationId: dify_conversationId.value
      };
      // 为什么这样写,如果不这样写,deepseek返回的标签<detail>在后端存不了
      const jsonString = JSON.stringify(createParams);
      //将JSON字符申写入一个BLob对象
      const blob = new Blob([jsonString], { type: 'application/json' });
      //创建一个FormData对象
      const formData = new FormData();
      formData.append('file', blob, 'data.json');
      apiChatReCreate(formData);
    }
    if (messages.length > 1) {
      //更新会话
      updateParams = {
        id: chatListId.value,
        title: messages[0].content,
        record: JSON.stringify(chatList.value),
        reCount: chatList.value.length,
        userId: userStore.userId,
        appId: ModelListRow.value.id,
        conversationId: dify_conversationId.value
      };

      const jsonString = JSON.stringify(updateParams);
      //将JSON字符申写入一个BLob对象
      const blob = new Blob([jsonString], { type: 'application/json' });
      //创建一个FormData对象
      const formData = new FormData();
      formData.append('file', blob, 'data.json');
      apiChatReModify(formData);
    }
  }

  // 知乎部分
  let zhihuParams = {
    title: messages[messages.length - 1].content,
    text: chatList.value[chatList.value.length - 1].msg,
    type: isContextShow.value ? 14 : 21, //14语境中心,21:普通对话
    tap: 2, //1是富文本 2 Markdown
    chatClassifyId: ContextMessage.value.type ? ContextMessage.value.type : '',
    chatClassifyName: ContextMessage.value.titleName ? ContextMessage.value.titleName : ''
  };

  apiKownChatInsertChatQuestion(zhihuParams);
};
//创建对话- 消息发送成功之后创建对话api
const apiChatReCreate = (params: any) => {
  aiqaWikiRecordCreate(params)
    .then((res: any) => {
      // if (isContextShow.value) {
      // apiHelperGet();//获取语境中心
      // } else {
      apiChatReGet();
      // }
      chatListId.value = res.data.id;
    })
    .catch((err) => {
      console.log(err);
      proxy.$modal.msgError(proxy.$t('chatGpt.chatMsg10'));
    });
};

//更新会话-消息发送成功之后更新会话api
const apiChatReModify = (params: any) => {
  aiqaWikiRecordUpdate(params)
    .then((res: any) => {
      // if (isContextShow.value) {
      //   // apiHelperGet();//获取语境中心
      // } else {
      apiChatReGet();
      // }
    })
    .catch((err) => {
      console.log(err);
      proxy.$modal.msgError(proxy.$t('chatGpt.chatMsg11'));
    });
};
//知乎创建问题
const apiKownChatInsertChatQuestion = (params: any) => {
  // chatWindowApi.apiKownChatInsertChatQuestion(params).catch((err: any) => {
  //   proxy.$modal.msgError(proxy.$t("chatGpt.chatMsg12"));
  // });
};
// 发送消息---往聊天数组中塞一条数据
const sendMsg = (val: any) => {
  chatList.value.push(val);
  scrollBottom();
};
//获取窗口高度并滚动至最底层
const scrollBottom = () => {
  nextTick(() => {
    setTimeout(() => {
      const scrollDom = chatContent.value;
      proxy.$yuUtils.animation(scrollDom, scrollDom.scrollHeight - scrollDom.offsetHeight);
    }, 300);
  });
};
// 显示应用文档
const showFastQuoteDocClick = (str: any) => {
  try {
    let quoteList = JSON.parse(str)[0].quoteList;
    const sourceNames = new Set(quoteList.map((item) => item && item.sourceName));
    const uniqueSourceNames = Array.from(sourceNames);
    return uniqueSourceNames;
    // console.log(uniqueSourceNames);
  } catch (error) {
    // console.log(error, "showFastQuoteDocClick");
    return [];
  }
};
//解析知识库文档应用
const textJsonParseFunc = (str: any) => {
  try {
    return JSON.parse(str)[0];
  } catch (error) {
    console.log(error, 'textJsonParseFunc');
    return {
      quoteList: [],
      runningTime: 0
    };
  }
};
// 打开FASTGPT知识库引用对话框
const openFastGptQuoteClick = (val: any) => {};
// 打开Dify知识库引用对话框
const openDifyQuoteClick = (val: any) => {
  DifyQuoteRefs.value.visibleDialog = true;
  DifyQuoteRefs.value.quoteList = val;
  console.log(val);
};
/**input事件-------------------------start */

// 键盘按下事件--阻止回车换行,执行ctrl + enter换行
const handleKeyPress = (event: any) => {
  console.log(event);
  if (event.keyCode == 13) {
    if (!event.ctrlKey) {
      event.preventDefault();
    } else {
      inputMsg.value += '\n';
    }
  }
};
const enterSubmit = (e) => {
  e.preventDefault();
  sendText();
};
/**input事件-------------------------end */

/**语言录入----------------------------start */
// 开始录音
const startRecordAudio = () => {
  //@ts-ignore
  Recorder?.getPermission().then(
    () => {
      // console.log("开始录音");
      recorder.start(); // 开始录音
      inputMsg.value = '';
      isSpeakType.value = 2;
    },
    (error: any) => {
      proxy.$modal.msgWarning('请先允许该网页使用麦克风');
      // console.log(`${error.name} : ${error.message}`);
    }
  );
};
// 停止录音
const stopRecordAudio = () => {
  recorder.stop();
  var wavBlob = recorder.getWAVBlob();
  isSpeakType.value = 3;
  var formData = new FormData();
  const newbolb = new Blob([wavBlob], { type: 'audio/wav' });
  // //获取当时时间戳作为文件名
  const fileOfBlob = new File([newbolb], new Date().getTime() + '.wav');
  formData.append('file', fileOfBlob);
  axios
    .post('/stt', formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    })
    .then((res) => {
      console.log(res);
      inputMsg.value = res.data;
      isSpeakType.value = 1;
      textInputRefs.value.focus();
    })
    .catch((err) => {
      isSpeakType.value = 1;
      proxy.$modal.msgError('语音识别失败，请重试');
    });
};
/**语言录入----------------------------end */
//复制
const copyClick = async (textToCopy: any) => {
  try {
    // await navigator.clipboard.writeText(textToCopy);
    if (proxy?.$yuUtils.YUcopyToClipboard(textToCopy)) {
      proxy?.$modal.msgSuccess('已复制到剪贴板!');
    } else {
      proxy.$modal.msgError('复制失败!');
    }
  } catch (err) {
    proxy.$modal.msgError('复制失败!');
    console.log(err);
  }
};
//图标转换
const selectSvgIcons = (v: any) => {
  let suffix = v.split('.')[1];
  return proxy.$yuUtils.selectSvgIcon({ suffix: suffix });
};
const listFootRef = ref<HTMLElement | null>(null);
// 播放音频---item.isAudio(播放:play 暂停:pause)
const playAudioClick = (item: any) => {
  if ('speechSynthesis' in window) {
    chatList.value.forEach((v: any) => {
      v.isAudio = 'play';
      pauseAudioClick(v);
    });
    const utterance = new SpeechSynthesisUtterance(item.msg);
    utterance.lang = 'zh-CN'; // 设置语言为中文
    utterance.rate = 0.8; // 设置语速为0.8倍（正常语速）
    utterance.pitch = 1; // 设置音调为1（正常音调）
    utterance.volume = 1; // 设置音量（1为最大音量）

    // 监听语音播放结束事件
    utterance.onend = () => {
      // 在这里可以添加其他逻辑，比如更新UI状态等
      item.isAudio = 'play'; // 恢复播放图标
    };
    speechSynthesis.speak(utterance);
    item.isAudio = 'pause';
  } else {
    proxy.$modal.msgWarning('当前浏览器不支持语音合成功能!');
  }
};
// 暂停音频
const pauseAudioClick = (item?: any) => {
  speechSynthesis?.cancel();
  if (item) {
    item.isAudio = 'play'; // 恢复播放图标
  }
};
// 从企业知识库跳转过来的链接
const getEnterpriseInfo = (aiDatasetId) => {
  aiqaWikiAppsGetAuthorizedByDataSetId({ dataSetId: aiDatasetId }).then((res: any) => {
    startChatClick_classifyList(res.data);
  });
};

onMounted(() => {
  apiChatReGet();
  if (route.query.aiDatasetId) {
    getEnterpriseInfo(route.query.aiDatasetId);
  }

  window.onbeforeunload = function (event) {
    // 这里不能执行异步操作
    pauseAudioClick();
  };
});

onBeforeUnmount(() => {
  pauseAudioClick();
  window.removeEventListener('beforeunload', pauseAudioClick);
});
</script>

<style scoped lang="scss">
$fontColor: #272a37;
$headerHeight: 70px;
$footHeight: 200px;
// $leftWidth1: 70px;
$leftWidth: 261px;
$rightCenterWidth: 845px;

@mixin textOverflow($clamp) {
  text-overflow: ellipsis;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: $clamp; //元素几行显示
  -webkit-box-orient: vertical;
}

.pageBox {
  display: flex;
  width: 100%;
  height: calc(100vh - 50px);
  height: calc(100vh - 50px);
  background-image: url('../../assets//images/chatgpt/bg.png');
  /* 替换为你的图片路径 */
  background-size: cover;
  /* 背景图片覆盖整个容器 */
  background-position: center;
  /* 背景图片居中显示 */
  background-repeat: no-repeat;
  /* 防止背景图片重复 */

  .pageLeft {
    padding-top: 12px;
    width: $leftWidth;
    height: 100%;
    border-right: 1px solid #ffe096;
    overflow-y: auto;
    // background: linear-gradient(to top, #fff7e9, white, #fff7e9);
    background-color: rgba(255, 255, 255, 0.5);
    position: relative;
  }

  .pageRight {
    width: calc(100% - $leftWidth);
    position: relative;
    transition: all 0.3s;
    overflow-x: auto;
  }

  .pageRight1 {
    width: 100%;
    position: relative;
    transition: all 0.3s;
    overflow-x: auto;
  }

  .packUpBtn {
    position: absolute;
    padding: 4px 12px 2px 6px;
    left: 0px;
    top: 50%;
    z-index: 1000;
    color: #f09207;
    border-radius: 0 18px 18px 0;
    transition: all 0.3s;
    cursor: pointer;

    &:hover {
      background-color: #f3d7a1;
    }
  }

  .page_body {
    height: 100%;
    overflow-y: auto;
  }
}

.historyDiv {
  width: calc($leftWidth - 2px);
}

.left_width1 {
  animation: slide-left 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}

.left_width2 {
  animation: slide-right 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}

@keyframes slide-left {
  0% {
    width: $leftWidth;
  }

  100% {
    width: 0px;
  }
}

@keyframes slide-right {
  0% {
    width: 0px;
  }

  100% {
    width: $leftWidth;
  }
}

.history_list_box {
  height: calc(100vh - 150px);
  overflow-y: auto;
}

.history_title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px;
  font-size: 14px;
  font-weight: bold;

  i {
    cursor: pointer;
  }
}

.history_delete_btn {
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: #c3c8cf;
  font-size: 12px;
  margin-top: 6px;

  .del_icon {
    font-size: 14px;

    &:hover {
      color: #f56c6c;
    }
  }
}

.history_item_box_active {
  background-color: #fef4e1;
  border-left: 2px solid #f0930c;

  .item_title {
    color: #f0930c !important;
  }
}

.history_item_box {
  color: #333333;
  padding: 13px 10px;
  cursor: pointer;
  border-left: 2px solid rgba(0, 0, 0, 0);
  margin-top: 6px;

  img {
    width: 22px;
    height: 22px;
    margin-right: 4px;
  }

  .item_title {
    font-size: 13px;
    color: #3d3d3d;
    @include textOverflow(1);
  }

  .item_title_cot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 2px;
    background-color: #f0930c;
  }
}

.history_item_box:hover {
  @extend .history_item_box_active;
}

.history_page {
  :deep(.el-pagination) {
    padding: 2px 0px;
  }

  :deep(.el-pagination .btn-next) {
    padding-left: 4px;
  }

  :deep(.el-pagination .btn-prev) {
    padding-right: 4px;
  }

  :deep(.el-pager li) {
    background-color: #fffcf6;
    min-width: 22px;
    color: #f08f00;
  }

  :deep(button) {
    background-color: #fffcf6 !important;
    color: #f08f00;
    min-width: 30px;
  }
}

.body_header {
  margin-bottom: 20px;

  .header_left_title {
    font-weight: bolder;
    font-style: italic;
    margin-left: 15px;
    margin-top: 15px;
  }

  .left_title_text {
    background: linear-gradient(to right, #cc687b, #507de3);
    background-clip: text;
    -webkit-text-fill-color: transparent;
  }

  .header_big_title {
    text-align: center;
    position: relative;
    height: 100px;

    .img_box {
      position: absolute;
      top: 12px;
      left: 50%;
      width: 280px;
      transform: translate(-50%, 0);
    }
  }

  .big_title_text {
    position: absolute;
    bottom: 0;
    left: 50%;
    transform: translate(-50%, 0);
    font-size: 30px;
    font-weight: bolder;
    color: #ffffff;
    background: linear-gradient(0deg, #ff4d45 0%, #f08f00 0%, #ff4d45 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    font-family: FZZongYi-M05S;

    .right_text {
      margin-left: 10px;
    }
  }
}

.page_input {
  max-width: 800px;
  margin: 0 auto;
  display: flex;
  justify-content: center;
  align-items: flex-end;

  .create_btn {
    margin-left: 8px;
    // margin-bottom: 8px;
  }

  .img2 {
    width: 16px;
    height: 16px;
  }

  .input_box {
    flex: 1;
    display: flex;
    align-items: flex-end;
    background-color: #ffffff;
    border-radius: 6px;
    border: 1px solid #ffdeae;
    box-shadow: 0px 0px 8px 0px rgba(240, 143, 0, 0.06);

    // height: 60px;
    padding: 8px;
    margin: 0 auto;

    :deep(.el-textarea__inner) {
      box-shadow: none;
      // background-color: #3662ec;
    }

    .btn_box {
      display: flex;
      align-items: center;
    }
  }

  .sendBtn {
    width: 28px;
    height: 28px;
    text-align: center;
    line-height: 28px;
    background-color: #f08f00;
    color: #ffffff;
    border-radius: 6px;
    // margin-left: 8px;
    font-size: 17px;
    cursor: pointer;
  }
}

// 语言录入动画-------------------start
.voice_box {
  cursor: pointer;

  .SpeakType3 {
    width: 60px;
    font-size: 12px;
    color: #b3b0c3;
  }
}

.loaderRectangle {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 0 3px;
}

.loaderRectangle div {
  width: 4px;
  height: 8px;
  animation: 0.9s ease-in-out infinite;
  background: #3662ec;
  box-shadow: 0 0 20px rgba(18, 31, 53, 0.3);
}

.loaderRectangle div:nth-child(1) {
  animation-name: rectangleOneAnim;
  animation-delay: 1s;
}

@keyframes rectangleOneAnim {
  0% {
    height: 8px;
  }

  40% {
    height: 15px;
  }

  100% {
    height: 8px;
  }
}

.loaderRectangle div:nth-child(2) {
  animation-name: rectangleTwoAnim;
  animation-delay: 1.1s;
}

@keyframes rectangleTwoAnim {
  0% {
    height: 8px;
  }

  40% {
    height: 20px;
  }

  100% {
    height: 8px;
  }
}

.loaderRectangle div:nth-child(3) {
  animation-name: rectangleThreeAnim;
  animation-delay: 1.2s;
}

@keyframes rectangleThreeAnim {
  0% {
    height: 8px;
  }

  40% {
    height: 25px;
  }

  100% {
    height: 8px;
  }
}

.loaderRectangle div:nth-child(4) {
  animation-name: rectangleFourAnim;
  animation-delay: 1.3s;
}

@keyframes rectangleFourAnim {
  0% {
    height: 8px;
  }

  40% {
    height: 20px;
  }

  100% {
    height: 8px;
  }
}

.loaderRectangle div:nth-child(5) {
  animation-name: rectangleFiveAnim;
  animation-delay: 1.4s;
}

@keyframes rectangleFiveAnim {
  0% {
    height: 8px;
  }

  40% {
    height: 15px;
  }

  100% {
    height: 8px;
  }
}

// 语言录入动画-------------------end
// 聊天列表
.chit_chat {
  width: 100%;
  // height: calc(100vh - $headerHeight - $footHeight);
  height: calc(100vh - $footHeight);
  padding: 40px 10px 20px;
}

.chat_list {
  width: calc($rightCenterWidth - 10px);
  margin: 0 auto;
  // margin-left: calc((100% - $rightCenterWidth - 200px) / 2);
  height: 100%;
  overflow-y: auto;

  &::-webkit-scrollbar {
    width: 6px;
    /* 设置滚动条宽度 */
  }

  .list_item {
    display: flex;
  }

  .list_item_user {
    justify-content: flex-end;
  }

  .chat_logoIcon {
    width: 50px;
    height: 50px;
    margin: 0 8px 0 0px;
  }

  .right_text_box {
    width: calc(100% - 100px);

    .name {
      font-size: 14px;
      font-weight: bold;
      color: #464358;
      margin-bottom: 12px;
      display: flex;
      align-items: center;

      img {
        margin-right: 8px;
      }
    }
  }

  .right_text_header {
    padding: 24px 20px 20px 26px !important;
  }

  .right_text {
    // width: calc(100% - 100px);
    // padding: 24px 20px 20px 26px;
    // padding: 6px;
    border-radius: 15px 15px 15px 15px;
    color: #3d3d3d;
    font-size: 16px;
    margin-bottom: 15px;
    // background-color: #ffffff;

    .ai_text1 {
      // color: #5d78ea;
      color: #f08f00;
      line-height: 22px;
      margin-bottom: 4px;
    }

    .ai_text2 {
      line-height: 22px;
    }

    :deep(.el-textarea__inner) {
      box-shadow: none;
      padding-left: 0 !important;
      font-size: 16px;
      min-height: 34px;
      background-color: rgba(0, 0, 0, 0);
      color: #ffffff;
    }

    .input_textarea_msg {
      width: 100%;
    }
  }

  .ai_right_text {
    background-color: #ffffff;
    max-width: 707px;
    overflow: hidden;
    padding-top: 10px;
    padding-bottom: 10px;
    // :deep(p) {
    //   margin: 15px 0 !important;
    //   line-height: 23px;

    // }

    // :deep(code) {
    //   // background-color: #f9f9f9;
    //   //font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
    //   //line-height: 24px;
    //   //-size: 15px;
    // }

    // :deep(summary) {
    //   margin: 15px 0;
    // }
  }

  .user_right_text {
    background-color: #2d65f7;
    margin-right: 10px;
    color: #fff;
    padding: 0px 16px;
    max-width: 707px;

    pre {
      white-space: pre-wrap;
      /*css-3*/

      white-space: -moz-pre-wrap;
      /*Mozilla,since1999*/

      white-space: -pre-wrap;
      /*Opera4-6*/

      white-space: -o-pre-wrap;
      /*Opera7*/

      word-wrap: break-word;
      /*InternetExplorer5.5+*/
      font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
    }
  }

  .list_foot {
    display: flex;
    // justify-content: space-between;
    visibility: hidden;
    padding: 0px 0 8px;

    .div_icon {
      background-color: #ffffff;
      box-shadow:
        rgba(16, 24, 40, 0.1) 0px 4px 8px -2px,
        rgba(16, 24, 40, 0.06) 0px 2px 4px -2px;
      border-radius: 6px;
      padding: 7px 6px 3px;
      margin-right: 5px;
      color: #667085;
      cursor: pointer;

      &:hover {
        color: #f08f00;
      }
    }

    .div_icon_volume {
      padding: 6px 6px 4px;
    }

    .reanswer_btn {
      font-size: 12px;
      color: #8789ad;
      font-weight: 500;
      cursor: pointer;
      display: flex;
      align-items: center;

      img {
        margin-right: 5px;
      }
    }

    .copy {
      cursor: pointer;
    }
  }
}

.right_text_box:hover {
  .list_foot {
    visibility: visible;
  }
}

.last_foot_visible {
  visibility: visible !important;
}

.ai_logo {
  width: 40px;
  height: 40px;
  margin: 0 15px 0 0px;
  // background-color: #5b9bfc;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 25px;
  font-size: 40px;

  .svgIconLogo {
  }

  img {
    width: 30px;
  }
}

.user-avatar {
  cursor: pointer;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  margin-top: 10px;
}

/* 引用块的样式 */
:deep(blockquote) {
  display: block;
  padding-left: 16px;
  padding-right: 16px;
  margin: 0 0 24px;
  border-left: 8px solid #dddfe4;
  background-color: #eef0f4;
  overflow: auto;
  word-break: normal;
}

/** 代码引用 */
:deep(code:not(.hljs)) {
  padding: 2px 4px;
  color: #c7254e;
  background-color: #f9f2f4;
  border-radius: 2px;
}

.unfold_btn {
  position: absolute;
  left: 0;
  bottom: 0;
  display: flex;
  justify-content: space-between;
  // margin-top: 20px;
  width: 100%;
  border-top: 1px solid #ffeec8;
  border-bottom: 1px solid #ffeec8;

  .btn1 {
    // width: 115px;
    flex: 1;
    height: 42px;
    line-height: 42px;
    padding: 0 17px;
    text-align: center;
    color: #000000;
    font-size: 12px;
    font-weight: bold;
    cursor: pointer;
    display: flex;
    align-items: center;
    border-right: 1px solid #ffeec8;

    .img1 {
      width: 20px;
      height: 20px;
      margin-right: 4px;
    }

    .img2 {
      width: 14px;
      margin-right: 8px;
    }

    span {
      @include textOverflow(1);
    }
  }

  .btn1:hover {
    background-color: #f1f2f3;
  }
}

.new_btn {
  width: 100%;
  padding: 5px;
}
.dify_box {
  padding: 0 20px;
}
.quote_list {
  overflow-x: auto;
}

.falstelTag {
  margin-right: 5px;
  margin-bottom: 5px;
  cursor: pointer;
}

.stop_box {
  display: flex;
  align-items: center;
  margin-top: 5px;
  padding-left: 20px;

  .stop_icon {
    margin-left: 5px;
    cursor: pointer;
  }
}
</style>
